/*
 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_IMAGE_IMAGE_MODEL_NG_CPP
#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_IMAGE_IMAGE_MODEL_NG_CPP

#include "core/components_ng/pattern/image/image_model_ng.h"

#include "interfaces/native/node/resource.h"

#include "base/image/image_defines.h"
#include "core/components/common/layout/constants.h"
#include "core/components/image/image_theme.h"
#include "core/components_ng/base/frame_node.h"
#include "core/components_ng/base/view_stack_processor.h"
#include "core/components_ng/pattern/image/image_render_property.h"
#include "core/components_ng/pattern/text/span_node.h"
#include "core/image/image_source_info.h"
#ifndef ACE_UNITTEST
#include "core/components_ng/base/view_abstract.h"
#endif
#include "core/common/resource/resource_manager.h"
#include "core/common/resource/resource_parse_utils.h"

namespace OHOS::Ace::NG {
namespace {
const std::vector<float> DEFAULT_COLOR_FILTER = { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 };
constexpr float DEFAULT_HDR_BRIGHTNESS = 1.0f;
ImageSourceInfo CreateSourceInfo(const std::shared_ptr<std::string>& src, RefPtr<PixelMap>& pixmap,
    const std::string& bundleName, const std::string& moduleName)
{
#if defined(PIXEL_MAP_SUPPORTED)
    if (pixmap) {
        return ImageSourceInfo(pixmap);
    }
#endif
    return { src, bundleName, moduleName };
}

ImageSourceInfo CreateSourceInfo(
    const std::string& src, RefPtr<PixelMap>& pixmap, const std::string& bundleName, const std::string& moduleName)
{
#if defined(PIXEL_MAP_SUPPORTED)
    if (pixmap) {
        return ImageSourceInfo(pixmap);
    }
#endif
    return { src, bundleName, moduleName };
}
} // namespace

void SetFrameNodeDraggable(RefPtr<FrameNode>& frameNode, bool isImageSpan)
{
    if (!isImageSpan) {
        auto pipeline = frameNode->GetContext();
        CHECK_NULL_VOID(pipeline);
        auto draggable = pipeline->GetDraggable<ImageTheme>();
        if (draggable && !frameNode->IsDraggable()) {
            auto gestureHub = frameNode->GetOrCreateGestureEventHub();
            CHECK_NULL_VOID(gestureHub);
            gestureHub->InitDragDropEvent();
        }
        frameNode->SetDraggable(draggable);
    }
}

void ImageModelNG::Create(ImageInfoConfig& imageInfoConfig)
{
    auto* stack = ViewStackProcessor::GetInstance();
    auto nodeId = stack->ClaimNodeId();
    const std::string& src = imageInfoConfig.src ? *imageInfoConfig.src : "";
    ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d] [src:%s]", V2::IMAGE_ETS_TAG, nodeId, src.c_str());
    RefPtr<FrameNode> frameNode;
    if (imageInfoConfig.isImageSpan) {
        frameNode = ImageSpanNode::GetOrCreateSpanNode(
            V2::IMAGE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
    } else {
        frameNode = FrameNode::GetOrCreateFrameNode(
            V2::IMAGE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
    }
    stack->Push(frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    // set draggable for framenode
    SetFrameNodeDraggable(frameNode, imageInfoConfig.isImageSpan);
    pattern->SetImageType(imageInfoConfig.type);
    pattern->SetNeedLoadAlt(true);
    pattern->UpdateDrawableDescriptor(imageInfoConfig.drawable);
    if (imageInfoConfig.type != ImageType::ANIMATED_DRAWABLE) {
        auto srcInfo = CreateSourceInfo(
            imageInfoConfig.src, imageInfoConfig.pixelMap, imageInfoConfig.bundleName, imageInfoConfig.moduleName);
        srcInfo.SetIsUriPureNumber(imageInfoConfig.isUriPureNumber);
        ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo);
    }
    SetImageFillSetByUser(false);
}

void ImageModelNG::ResetImage()
{
    auto* stack = ViewStackProcessor::GetInstance();
    auto nodeId = stack->ClaimNodeId();
    RefPtr<FrameNode> frameNode;
    frameNode = FrameNode::GetOrCreateFrameNode(
        V2::IMAGE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
    stack->Push(frameNode);
    ImageSourceInfo sourceInfo("");
    sourceInfo.SetIsFromReset(true);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, sourceInfo, frameNode);
    frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
    SetFrameNodeDraggable(frameNode, false);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedLoadAlt(false);
    pattern->ResetImageAndAlt();
    pattern->ResetDrawableDescriptor();
}

void ImageModelNG::ResetImage(FrameNode* frameNode)
{
    ImageSourceInfo sourceInfo("");
    sourceInfo.SetIsFromReset(true);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, sourceInfo, frameNode);
    frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedLoadAlt(false);
    pattern->ResetImageAndAlt();
}

void ImageModelNG::SetInitialSrc(FrameNode* frameNode, const std::string& src, const std::string& bundleName,
    const std::string& moduleName, bool isUriPureNumber)
{
    auto srcInfo = ImageSourceInfo { src, bundleName, moduleName };
    srcInfo.SetIsUriPureNumber(isUriPureNumber);

    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo, frameNode);
}

void ImageModelNG::SetInitialPixelMap(FrameNode* frameNode, RefPtr<PixelMap>& pixMap)
{
    auto srcInfo = ImageSourceInfo(pixMap);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo, frameNode);
}

RefPtr<FrameNode> ImageModelNG::CreateFrameNode(int32_t nodeId, const std::string& src, RefPtr<PixelMap>& pixMap,
    const std::string& bundleName, const std::string& moduleName, bool isUriPureNumber)
{
    auto frameNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, nodeId, AceType::MakeRefPtr<ImagePattern>());
    CHECK_NULL_RETURN(frameNode, nullptr);
    // set draggable for framenode
    auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
    CHECK_NULL_RETURN(pipeline, nullptr);
    auto draggable = pipeline->GetDraggable<ImageTheme>();
    if (draggable && !frameNode->IsDraggable()) {
        auto gestureHub = frameNode->GetOrCreateGestureEventHub();
        CHECK_NULL_RETURN(gestureHub, nullptr);
        gestureHub->InitDragDropEvent();
    }
    frameNode->SetDraggable(draggable);
    auto srcInfo = CreateSourceInfo(src, pixMap, bundleName, moduleName);
    srcInfo.SetIsUriPureNumber(isUriPureNumber);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, nullptr);
    layoutProperty->UpdateImageSourceInfo(srcInfo);
    return frameNode;
}

void ImageModelNG::SetAlt(const ImageSourceInfo& src)
{
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, Alt, src);
}

void ImageModelNG::SetSmoothEdge(float value)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, SmoothEdge, value);
}

void ImageModelNG::SetSmoothEdge(FrameNode* frameNode, float value)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, SmoothEdge, value, frameNode);
}

void ImageModelNG::SetDynamicRangeMode(DynamicRangeMode dynamicRangeMode)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, dynamicRangeMode);
    ACE_UPDATE_RENDER_CONTEXT(DynamicRangeMode, dynamicRangeMode);
}

void ImageModelNG::SetDynamicRangeMode(FrameNode* frameNode, DynamicRangeMode dynamicRangeMode)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, dynamicRangeMode, frameNode);
    ACE_UPDATE_NODE_RENDER_CONTEXT(DynamicRangeMode, dynamicRangeMode, frameNode);
}

void ImageModelNG::SetHdrBrightness(float hdrBrightness)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, HdrBrightness, hdrBrightness);
}

void ImageModelNG::SetHdrBrightness(FrameNode* frameNode, float hdrBrightness)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, HdrBrightness, hdrBrightness, frameNode);
}

void ImageModelNG::SetEnhancedImageQuality(AIImageQuality imageQuality)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetImageQuality(imageQuality);
}

void ImageModelNG::SetEnhancedImageQuality(FrameNode* frameNode, AIImageQuality imageQuality)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>(frameNode);
    CHECK_NULL_VOID(pattern);
    pattern->SetImageQuality(imageQuality);
}

void ImageModelNG::SetBorder(const Border& border) {}

void ImageModelNG::SetBorderRadius(const Dimension& value)
{
    BorderRadiusProperty borderRadius;
    borderRadius.SetRadius(value);
    borderRadius.multiValued = false;
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true);
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius);
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBorderRadius(const std::optional<Dimension>& radiusTopLeft,
    const std::optional<Dimension>& radiusTopRight, const std::optional<Dimension>& radiusBottomLeft,
    const std::optional<Dimension>& radiusBottomRight)
{
    NG::BorderRadiusProperty borderRadius;
    borderRadius.radiusTopLeft = radiusTopLeft;
    borderRadius.radiusTopRight = radiusTopRight;
    borderRadius.radiusBottomLeft = radiusBottomLeft;
    borderRadius.radiusBottomRight = radiusBottomRight;
    borderRadius.multiValued = true;
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true);
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius);
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBorderRadius(const NG::BorderRadiusProperty& borderRadius)
{
    if (SystemProperties::ConfigChangePerform()) {
        std::string key = "image.borderRadius.edges";
        std::string borderRadiusKey = "image.borderRadius";
        std::string radiusKey = "borderRadius";
        auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
        CHECK_NULL_VOID(frameNode);
        auto pattern = frameNode->GetPattern<ImagePattern>();
        CHECK_NULL_VOID(pattern);
        pattern->RemoveResObj(key);
        pattern->RemoveResObj(borderRadiusKey);
        pattern->RemoveResObj(radiusKey);
        RefPtr<ResourceObject> resObj = AceType::MakeRefPtr<ResourceObject>("", "", -1);
        auto&& updateFunc = [borderRadius, weak = AceType::WeakClaim(frameNode)](const RefPtr<ResourceObject>& resObj) {
            auto frameNode = weak.Upgrade();
            CHECK_NULL_VOID(frameNode);
            BorderRadiusProperty& borderRadiusReload = const_cast<BorderRadiusProperty&>(borderRadius);
            borderRadiusReload.ReloadResources();
            ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
            ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadiusReload, frameNode);
            auto pattern = frameNode->GetPattern<ImagePattern>();
            CHECK_NULL_VOID(pattern);
            pattern->SetNeedBorderRadius(true);
        };
        pattern->AddResObj(key, resObj, std::move(updateFunc));
    }
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true);
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius);
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBorderRadius(FrameNode* frameNode, const Dimension& value)
{
    BorderRadiusProperty borderRadius;
    borderRadius.SetRadius(value);
    borderRadius.multiValued = false;
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius, frameNode);
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBorderRadius(FrameNode* frameNode, const std::optional<Dimension>& radiusTopLeft,
    const std::optional<Dimension>& radiusTopRight, const std::optional<Dimension>& radiusBottomLeft,
    const std::optional<Dimension>& radiusBottomRight)
{
    NG::BorderRadiusProperty borderRadius;
    borderRadius.radiusTopLeft = radiusTopLeft;
    borderRadius.radiusTopRight = radiusTopRight;
    borderRadius.radiusBottomLeft = radiusBottomLeft;
    borderRadius.radiusBottomRight = radiusBottomRight;
    borderRadius.multiValued = true;
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBorderRadius(FrameNode* frameNode, const NG::BorderRadiusProperty& borderRadius)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBackBorder()
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true);
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::SetBackBorder(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(true);
}

void ImageModelNG::ResetBackBorder(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetNeedBorderRadius(false);
}

void ImageModelNG::SetBlur(double blur) {}

void ImageModelNG::SetImageFit(ImageFit value)
{
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageFit, value);
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageFit, value);
}

void ImageModelNG::SetImageMatrix(const Matrix4& value)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageMatrix, value);
}

void ImageModelNG::SetMatchTextDirection(bool value)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, MatchTextDirection, value);
}

void ImageModelNG::SetFitOriginSize(bool value)
{
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, FitOriginalSize, value);
}

void ImageModelNG::SetOnComplete(std::function<void(const LoadImageSuccessEvent& info)>&& callback)
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto eventHub = frameNode->GetEventHub<ImageEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnComplete(std::move(callback));
}

void ImageModelNG::SetOnError(std::function<void(const LoadImageFailEvent& info)>&& callback)
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto eventHub = frameNode->GetEventHub<ImageEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnError(std::move(callback));
}

void ImageModelNG::SetSvgAnimatorFinishEvent(std::function<void()>&& callback)
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto eventHub = frameNode->GetEventHub<ImageEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnFinish(std::move(callback));
}

void ImageModelNG::SetImageSourceSize(const std::pair<Dimension, Dimension>& size)
{
    SizeF sourceSize =
        SizeF(static_cast<float>(size.first.ConvertToPx()), static_cast<float>(size.second.ConvertToPx()));
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, SourceSize, sourceSize);
}

void ImageModelNG::SetImageFill(const Color& color)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, SvgFillColor, color);
    ACE_UPDATE_RENDER_CONTEXT(ForegroundColor, color);
}

void ImageModelNG::ResetImageFill()
{
    ACE_RESET_PAINT_PROPERTY_WITH_FLAG(ImageRenderProperty, SvgFillColor, PROPERTY_UPDATE_RENDER);
    ACE_RESET_RENDER_CONTEXT(RenderContext, ForegroundColor);
}

void ImageModelNG::ResetImageFill(FrameNode* frameNode)
{
    ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(ImageRenderProperty, SvgFillColor, PROPERTY_UPDATE_RENDER, frameNode);
    ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, ForegroundColor, frameNode);
}

void ImageModelNG::SetImageInterpolation(ImageInterpolation interpolation)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageInterpolation, interpolation);
}

void ImageModelNG::SetImageRepeat(ImageRepeat imageRepeat)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageRepeat, imageRepeat);
}

void ImageModelNG::SetImageRenderMode(ImageRenderMode imageRenderMode)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageRenderMode, imageRenderMode);
}

bool ImageModelNG::IsSrcSvgImage()
{
    return false;
}

void ImageModelNG::SetAutoResize(bool autoResize)
{
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, AutoResize, autoResize);
}

void ImageModelNG::SetSyncMode(bool syncMode)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetSyncLoad(syncMode);
}

void ImageModelNG::SetColorFilterMatrix(const std::vector<float>& matrix)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ColorFilter, matrix);
    ACE_RESET_PAINT_PROPERTY(ImageRenderProperty, DrawingColorFilter);
}

void ImageModelNG::SetDrawingColorFilter(RefPtr<DrawingColorFilter>& colorFilter)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, DrawingColorFilter, colorFilter);
    ACE_RESET_PAINT_PROPERTY(ImageRenderProperty, ColorFilter);
}

void ImageModelNG::SetDraggable(bool draggable)
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    auto gestureHub = ViewStackProcessor::GetInstance()->GetMainFrameNodeGestureEventHub();
    CHECK_NULL_VOID(gestureHub);
    if (draggable) {
        if (!frameNode->IsDraggable()) {
            gestureHub->InitDragDropEvent();
        }
    } else {
        gestureHub->RemoveDragEvent();
    }
    CHECK_NULL_VOID(frameNode);
    frameNode->SetCustomerDraggable(draggable);
}

void ImageModelNG::SetOnDragStart(OnDragStartFunc&& onDragStart)
{
#ifndef ACE_UNITTEST
    auto dragStart = [dragStartFunc = std::move(onDragStart)](
                         const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) -> DragDropInfo {
        auto dragInfo = dragStartFunc(event, extraParams);
        DragDropInfo info;
        info.extraInfo = dragInfo.extraInfo;
        info.pixelMap = dragInfo.pixelMap;
        info.customNode = AceType::DynamicCast<UINode>(dragInfo.node);
        return info;
    };
    ViewAbstract::SetOnDragStart(std::move(dragStart));
#endif
}

void ImageModelNG::SetOnDragEnter(OnDragDropFunc&& onDragEnter) {}

void ImageModelNG::SetOnDragLeave(OnDragDropFunc&& onDragLeave) {}

void ImageModelNG::SetOnDragMove(OnDragDropFunc&& onDragMove) {}

void ImageModelNG::SetOnDrop(OnDragDropFunc&& onDrop) {}

void ImageModelNG::SetCopyOption(const CopyOptions& copyOption)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetCopyOption(copyOption);
}

bool ImageModelNG::UpdateDragItemInfo(DragItemInfo& itemInfo)
{
    return false;
}

void ImageModelNG::InitImage(FrameNode* frameNode, std::string& src)
{
    std::string bundleName;
    std::string moduleName;
    RefPtr<OHOS::Ace::PixelMap> pixMapPtr;
    auto srcInfo = CreateSourceInfo(src, pixMapPtr, bundleName, moduleName);
    srcInfo.SetIsUriPureNumber(false);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo, frameNode);
}

void ImageModelNG::SetPixelMap(FrameNode* frameNode, void* drawableDescriptor)
{
#ifndef ACE_UNITTEST
    CHECK_NULL_VOID(drawableDescriptor);
    RefPtr<PixelMap> pixelMapPtr = PixelMap::GetFromDrawable(drawableDescriptor);
    auto srcInfo = CreateSourceInfo("", pixelMapPtr, "", "");
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo, frameNode);
#endif
}

void ImageModelNG::SetDrawableDescriptor(FrameNode* frameNode, void* newDrawableDescriptor)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>(frameNode);
    CHECK_NULL_VOID(pattern);
    auto* drawableAddr = reinterpret_cast<DrawableDescriptor*>(newDrawableDescriptor);
    CHECK_NULL_VOID(drawableAddr);
    auto drawableType = drawableAddr->GetDrawableType();
    if (drawableType != DrawableType::ANIMATED) {
        auto pixelMap = drawableAddr->GetPixelMap();
        auto srcInfo = ImageSourceInfo(pixelMap);
        ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo, frameNode);
    } else {
        auto drawable = Referenced::Claim<DrawableDescriptor>(drawableAddr);
        pattern->SetImageType(ImageType::ANIMATED_DRAWABLE);
        pattern->UpdateDrawableDescriptor(drawable);
    }
}

void ImageModelNG::SetResource(FrameNode* frameNode, void* resource)
{
    auto res = reinterpret_cast<ArkUI_Resource*>(resource);
    CHECK_NULL_VOID(res);
    RefPtr<PixelMap> pixMapPtr;
    auto srcInfo = CreateSourceInfo(res->src, pixMapPtr, res->bundleName, res->moduleName);
    srcInfo.SetIsUriPureNumber(res->resId == -1);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, srcInfo, frameNode);
}

void ImageModelNG::SetDrawingColorFilter(FrameNode* frameNode, RefPtr<DrawingColorFilter>& colorFilter)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, DrawingColorFilter, colorFilter, frameNode);
    ACE_RESET_NODE_PAINT_PROPERTY(ImageRenderProperty, ColorFilter, frameNode);
}

void ImageModelNG::SetCopyOption(FrameNode* frameNode, CopyOptions copyOption)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>(frameNode);
    CHECK_NULL_VOID(pattern);
    pattern->SetCopyOption(copyOption);
}

CopyOptions ImageModelNG::GetCopyOption(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, CopyOptions::None);
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>(frameNode);
    CHECK_NULL_RETURN(pattern, CopyOptions::None);
    return pattern->GetCopyOption();
}

void ImageModelNG::SetAutoResize(FrameNode* frameNode, bool autoResize)
{
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AutoResize, autoResize, frameNode);
}

void ImageModelNG::ResetAutoResize(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(imagePattern);
    auto defaultAutoResize = imagePattern->GetDefaultAutoResize();
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AutoResize, defaultAutoResize, frameNode);
}

void ImageModelNG::SetResizableSlice(ImageResizableSlice& slice)
{
    if (SystemProperties::ConfigChangePerform()) {
        auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
        CHECK_NULL_VOID(frameNode);
        auto pattern = frameNode->GetPattern();
        CHECK_NULL_VOID(pattern);
        std::string key = "image.ResizableSlice";
        RefPtr<ResourceObject> resObj = AceType::MakeRefPtr<ResourceObject>("", "", -1);
        auto&& updateFunc = [slice, weak = AceType::WeakClaim(frameNode)](const RefPtr<ResourceObject>& resObj) {
            auto frameNode = weak.Upgrade();
            if (!frameNode) {
                return;
            }
            ImageResizableSlice& sliceValue = const_cast<ImageResizableSlice&>(slice);
            sliceValue.ReloadResources();
            ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableSlice, sliceValue, frameNode);
        };
        pattern->AddResObj(key, resObj, std::move(updateFunc));
    }
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableSlice, slice);
}

void ImageModelNG::SetResizableSlice(FrameNode* frameNode, ImageResizableSlice& slice)
{
    CHECK_NULL_VOID(frameNode);
    if (SystemProperties::ConfigChangePerform()) {
        auto pattern = frameNode->GetPattern();
        CHECK_NULL_VOID(pattern);
        std::string key = "image.ResizableSlice";
        RefPtr<ResourceObject> resObj = AceType::MakeRefPtr<ResourceObject>("", "", -1);
        auto&& updateFunc = [slice, weak = AceType::WeakClaim(frameNode)](const RefPtr<ResourceObject>& resObj) {
            auto frameNode = weak.Upgrade();
            if (!frameNode) {
                return;
            }
            ImageResizableSlice& sliceValue = const_cast<ImageResizableSlice&>(slice);
            sliceValue.ReloadResources();
            ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableSlice, sliceValue, frameNode);
        };
        pattern->AddResObj(key, resObj, std::move(updateFunc));
    }
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableSlice, slice, frameNode);
}

void ImageModelNG::SetResizableLattice(const RefPtr<DrawingLattice>& lattice)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableLattice, lattice);
}

void ImageModelNG::SetResizableLattice(FrameNode* frameNode, const RefPtr<DrawingLattice>& lattice)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableLattice, lattice, frameNode);
}

void ImageModelNG::ResetResizableLattice()
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableLattice, nullptr);
}

void ImageModelNG::ResetResizableLattice(FrameNode* frameNode)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageResizableLattice, nullptr, frameNode);
}

void ImageModelNG::SetImageRepeat(FrameNode* frameNode, ImageRepeat imageRepeat)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageRepeat, imageRepeat, frameNode);
}

void ImageModelNG::SetImageRenderMode(FrameNode* frameNode, ImageRenderMode imageRenderMode)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageRenderMode, imageRenderMode, frameNode);
}

void ImageModelNG::SetImageMatrix(FrameNode* frameNode, const Matrix4& value)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageMatrix, value, frameNode);
}

void ImageModelNG::SetImageFit(FrameNode* frameNode, ImageFit value)
{
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageFit, value, frameNode);
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageFit, value, frameNode);
}

void ImageModelNG::SetFitOriginSize(FrameNode* frameNode, bool value)
{
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, FitOriginalSize, value, frameNode);
}

void ImageModelNG::SetSyncMode(FrameNode* frameNode, bool syncMode)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>(frameNode);
    CHECK_NULL_VOID(pattern);
    pattern->SetSyncLoad(syncMode);
}

void ImageModelNG::SetImageSourceSize(FrameNode* frameNode, const std::pair<Dimension, Dimension>& size)
{
    SizeF sourceSize =
        SizeF(static_cast<float>(size.first.ConvertToPx()), static_cast<float>(size.second.ConvertToPx()));
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, SourceSize, sourceSize, frameNode);
}

void ImageModelNG::SetMatchTextDirection(FrameNode* frameNode, bool value)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, MatchTextDirection, value, frameNode);
}

void ImageModelNG::SetImageFill(FrameNode* frameNode, const Color& color)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, SvgFillColor, color, frameNode);
    ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, color, frameNode);
}

void ImageModelNG::SetAlt(FrameNode* frameNode, const ImageSourceInfo& src)
{
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, Alt, src, frameNode);
}

void ImageModelNG::SetAltResource(FrameNode* frameNode, void* resource)
{
    CHECK_NULL_VOID(frameNode);
    auto res = reinterpret_cast<ArkUI_Resource*>(resource);
    CHECK_NULL_VOID(res);
    RefPtr<PixelMap> pixMapPtr = nullptr;
    auto srcInfo = CreateSourceInfo(res->src, pixMapPtr, res->bundleName, res->moduleName);
    srcInfo.SetIsUriPureNumber(res->resId == -1);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, Alt, srcInfo, frameNode);
}

void ImageModelNG::SetAltPixelMap(FrameNode* frameNode, void* pixelMap)
{
    CHECK_NULL_VOID(frameNode);
    CHECK_NULL_VOID(pixelMap);
#ifndef ACE_UNITTEST
    RefPtr<PixelMap> pixelMapPtr = PixelMap::GetFromDrawable(pixelMap);
    auto srcInfo = CreateSourceInfo("", pixelMapPtr, "", "");
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, Alt, srcInfo, frameNode);
#endif
}

void ImageModelNG::SetImageInterpolation(FrameNode* frameNode, ImageInterpolation interpolation)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageInterpolation, interpolation, frameNode);
}

void ImageModelNG::ResetImageInterpolation(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(imagePattern);
    auto defaultInterpolation = imagePattern->GetDefaultInterpolation();
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ImageInterpolation, defaultInterpolation, frameNode);
}

void ImageModelNG::SetColorFilterMatrix(FrameNode* frameNode, const std::vector<float>& matrix)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ColorFilter, matrix, frameNode);
    ACE_RESET_NODE_PAINT_PROPERTY(ImageRenderProperty, DrawingColorFilter, frameNode);
}

void ImageModelNG::SetDraggable(FrameNode* frameNode, bool draggable)
{
    auto gestureHub = frameNode->GetOrCreateGestureEventHub();
    CHECK_NULL_VOID(gestureHub);
    if (draggable) {
        if (!frameNode->IsDraggable()) {
            gestureHub->InitDragDropEvent();
        }
    } else {
        gestureHub->RemoveDragEvent();
    }
    frameNode->SetCustomerDraggable(draggable);
}

void ImageModelNG::EnableAnalyzer(bool isEnableAnalyzer)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->EnableAnalyzer(isEnableAnalyzer);
}

void ImageModelNG::SetImageAnalyzerConfig(const ImageAnalyzerConfig& config)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetImageAnalyzerConfig(config);
}

void ImageModelNG::SetImageAnalyzerConfig(void* config)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetImageAnalyzerConfig(config);
}

void ImageModelNG::SetImageAIOptions(void* options)
{
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetImageAIOptions(options);
}

bool ImageModelNG::IsSrcSvgImage(FrameNode* frameNode)
{
    return false;
}

void ImageModelNG::SetOnComplete(
    FrameNode* frameNode, std::function<void(const LoadImageSuccessEvent& info)>&& callback)
{
    CHECK_NULL_VOID(frameNode);
    auto eventHub = frameNode->GetEventHub<ImageEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnComplete(std::move(callback));
}

void ImageModelNG::SetOnError(FrameNode* frameNode, std::function<void(const LoadImageFailEvent& info)>&& callback)
{
    CHECK_NULL_VOID(frameNode);
    auto eventHub = frameNode->GetEventHub<ImageEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnError(std::move(callback));
}

void ImageModelNG::SetOnSvgPlayFinish(FrameNode* frameNode, std::function<void()>&& callback)
{
    CHECK_NULL_VOID(frameNode);
    auto eventHub = frameNode->GetEventHub<ImageEventHub>();
    CHECK_NULL_VOID(eventHub);
    eventHub->SetOnFinish(std::move(callback));
}

void ImageModelNG::SetOnDownloadProgress(
    FrameNode* frameNode, std::function<void(const uint32_t& dlNow, const uint32_t& dlTotal)>&& callback)
{
    CHECK_NULL_VOID(frameNode);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(imagePattern);
    imagePattern->SetOnProgressCallback(std::move(callback));
}

ImageSourceInfo ImageModelNG::GetSrc(FrameNode* frameNode)
{
    ImageSourceInfo defaultImageSourceInfo;
    CHECK_NULL_RETURN(frameNode, defaultImageSourceInfo);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, defaultImageSourceInfo);
    return layoutProperty->GetImageSourceInfo().value_or(defaultImageSourceInfo);
}

ImageFit ImageModelNG::GetObjectFit(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, ImageFit::COVER);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, ImageFit::COVER);
    return layoutProperty->GetImageFit().value_or(ImageFit::COVER);
}

ImageRotateOrientation ImageModelNG::GetOrientation(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, ImageRotateOrientation::UP);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, ImageRotateOrientation::UP);
    return layoutProperty->GetImageRotateOrientation().value_or(ImageRotateOrientation::UP);
}

std::pair<CalcDimension, CalcDimension> ImageModelNG::GetImageSourceSize(FrameNode* frameNode)
{
    auto defaultSourceSize = std::pair<CalcDimension, CalcDimension>();
    CHECK_NULL_RETURN(frameNode, defaultSourceSize);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, defaultSourceSize);
    CHECK_NULL_RETURN(layoutProperty->GetImageSizeStyle(), defaultSourceSize);
    auto sourceSize = layoutProperty->GetImageSizeStyle()->GetSourceSize().value_or(SizeF());
    return std::make_pair(CalcDimension(sourceSize.Width()), CalcDimension(sourceSize.Height()));
}

float ImageModelNG::GetHdrBrightness(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, DEFAULT_HDR_BRIGHTNESS);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, DEFAULT_HDR_BRIGHTNESS);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), DEFAULT_HDR_BRIGHTNESS);
    return paintProperty->GetImagePaintStyle()->GetHdrBrightness().value_or(DEFAULT_HDR_BRIGHTNESS);
}

bool ImageModelNG::GetMatchTextDirection(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, false);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), false);
    return paintProperty->GetImagePaintStyle()->GetMatchTextDirection().value_or(false);
}

bool ImageModelNG::GetEnableAnalyzer(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_RETURN(imagePattern, false);
    return imagePattern->IsEnableAnalyzer();
}

DynamicRangeMode ImageModelNG::GetDynamicRangeMode(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, DynamicRangeMode::STANDARD);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, DynamicRangeMode::STANDARD);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), DynamicRangeMode::STANDARD);
    return paintProperty->GetImagePaintStyle()->GetDynamicMode().value_or(DynamicRangeMode::STANDARD);
}

Matrix4 ImageModelNG::GetImageMatrix(FrameNode* frameNode)
{
    Matrix4 matrix4;
    CHECK_NULL_RETURN(frameNode, matrix4);
    auto renderProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(renderProperty, matrix4);
    return renderProperty->GetImageMatrix().value_or(matrix4);
}

ImageInterpolation ImageModelNG::GetInterpolation(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, ImageInterpolation::NONE);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_RETURN(imagePattern, ImageInterpolation::NONE);
    auto defaultInterpolation = imagePattern->GetDefaultInterpolation();
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, defaultInterpolation);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), defaultInterpolation);
    return paintProperty->GetImagePaintStyle()->GetImageInterpolation().value_or(defaultInterpolation);
}

ImageRepeat ImageModelNG::GetObjectRepeat(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, ImageRepeat::NO_REPEAT);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, ImageRepeat::NO_REPEAT);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), ImageRepeat::NO_REPEAT);
    return paintProperty->GetImagePaintStyle()->GetImageRepeat().value_or(ImageRepeat::NO_REPEAT);
}

std::vector<float> ImageModelNG::GetColorFilter(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, DEFAULT_COLOR_FILTER);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, DEFAULT_COLOR_FILTER);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), DEFAULT_COLOR_FILTER);
    return paintProperty->GetImagePaintStyle()->GetColorFilter().value_or(DEFAULT_COLOR_FILTER);
}

RefPtr<DrawingColorFilter> ImageModelNG::GetDrawingColorFilter(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, nullptr);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, nullptr);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), nullptr);
    return paintProperty->GetImagePaintStyle()->GetDrawingColorFilter().value_or(nullptr);
}

bool ImageModelNG::GetAutoResize(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, true);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_RETURN(imagePattern, true);
    auto defaultAutoResize = imagePattern->GetDefaultAutoResize();
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, defaultAutoResize);
    CHECK_NULL_RETURN(layoutProperty->GetImageSizeStyle(), defaultAutoResize);
    return layoutProperty->GetImageSizeStyle()->GetAutoResize().value_or(defaultAutoResize);
}

bool ImageModelNG::GetSyncLoad(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_RETURN(imagePattern, false);
    return imagePattern->GetSyncLoad();
}

ImageSourceInfo ImageModelNG::GetAlt(FrameNode* frameNode)
{
    ImageSourceInfo defaultImageSourceInfo;
    CHECK_NULL_RETURN(frameNode, defaultImageSourceInfo);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, defaultImageSourceInfo);
    return layoutProperty->GetAlt().value_or(defaultImageSourceInfo);
}

bool ImageModelNG::GetFitOriginalSize(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, false);
    return layoutProperty->GetImageSizeStyle()->GetFitOriginalSize().value_or(false);
}

uint32_t ImageModelNG::GetFillColor(FrameNode* frameNode)
{
    uint32_t errorCode = -1;
    CHECK_NULL_RETURN(frameNode, errorCode);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, errorCode);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), errorCode);
    Color color = paintProperty->GetImagePaintStyle()->GetSvgFillColor().value_or(Color());
    return color.GetValue();
}

bool ImageModelNG::GetDraggable(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    return frameNode->IsDraggable();
}

ImageRenderMode ImageModelNG::GetImageRenderMode(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, ImageRenderMode::ORIGINAL);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, ImageRenderMode::ORIGINAL);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), ImageRenderMode::ORIGINAL);
    return paintProperty->GetImagePaintStyle()->GetImageRenderMode().value_or(ImageRenderMode::ORIGINAL);
}

bool ImageModelNG::GetIsAnimation()
{
    auto pattern = GetImagePattern();
    CHECK_NULL_RETURN(pattern, false);
    return pattern->GetIsAnimation();
}

ImagePattern* ImageModelNG::GetImagePattern()
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_RETURN(frameNode, nullptr);
    return frameNode->GetPatternPtr<ImagePattern>();
}

ImageResizableSlice ImageModelNG::GetResizableSlice(FrameNode* frameNode)
{
    ImageResizableSlice resizable;
    CHECK_NULL_RETURN(frameNode, resizable);
    auto renderProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(renderProperty, resizable);
    return renderProperty->GetImageResizableSlice().value_or(resizable);
}

void ImageModelNG::EnableAnalyzer(FrameNode* frameNode, bool isEnableAnalyzer)
{
    CHECK_NULL_VOID(frameNode);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(imagePattern);
    imagePattern->EnableAnalyzer(isEnableAnalyzer);
}

void ImageModelNG::SetImageAnalyzerConfig(FrameNode* frameNode, void* config)
{
    CHECK_NULL_VOID(frameNode);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(imagePattern);
    imagePattern->SetImageAnalyzerConfig(config);
}

void ImageModelNG::ResetImageSrc(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    ImageSourceInfo sourceInfo("");
    sourceInfo.SetIsFromReset(true);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageSourceInfo, sourceInfo, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->ResetImage();
    pattern->ResetDrawableDescriptor();
}

void ImageModelNG::ResetImageAlt(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    ImageSourceInfo sourceInfo("");
    sourceInfo.SetIsFromReset(true);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, Alt, sourceInfo, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->ResetAltImage();
}

void ImageModelNG::SetOrientation(ImageRotateOrientation orientation)
{
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageRotateOrientation, orientation);
    auto pattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetOrientation(orientation);
}

void ImageModelNG::SetOrientation(FrameNode* frameNode, ImageRotateOrientation orientation)
{
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageRotateOrientation, orientation, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetOrientation(orientation);
}

void HandleSrcResource(const RefPtr<ResourceObject>& resObj, const RefPtr<ImagePattern>& pattern)
{
    std::string key = "image.src";
    pattern->RemoveResObj(key);
    CHECK_NULL_VOID(resObj);
    auto updateFunc = [weak = AceType::WeakClaim(AceType::RawPtr(pattern))](const RefPtr<ResourceObject>& resObj) {
        auto pattern = weak.Upgrade();
        CHECK_NULL_VOID(pattern);
        std::string src =
            ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetMediaPath(resObj->GetId());
        auto params = resObj->GetParams();
        if (src.empty() && params.size() && params[0].value.has_value()) {
            if (resObj->GetType() == static_cast<int32_t>(ResourceType::RAWFILE)) {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetRawfile(
                    params[0].value.value());
            } else {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetMediaPathByName(
                    params[0].value.value());
            }
        }
        if (resObj->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
            if (resObj->GetId() == -1 && params.size() && params[0].value.has_value()) {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetStringByName(
                    params[0].value.value());
            } else if (resObj->GetId() != -1) {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetString(
                    resObj->GetId());
            }
        }
        RefPtr<PixelMap> pixmap = nullptr;
        auto srcInfo = CreateSourceInfo(src, pixmap, resObj->GetBundleName(), resObj->GetModuleName());
        srcInfo.SetIsUriPureNumber(resObj->GetId() == -1);
        pattern->UpdateImageSourceinfo(srcInfo);
        pattern->OnConfigurationUpdate();
    };
    pattern->AddResObj(key, resObj, std::move(updateFunc));
}

void HandleAltResource(const RefPtr<ResourceObject>& resObj, const RefPtr<ImagePattern>& pattern)
{
    std::string key = "image.alt";
    pattern->RemoveResObj(key);
    CHECK_NULL_VOID(resObj);
    auto updateFunc = [weak = AceType::WeakClaim(AceType::RawPtr(pattern))](const RefPtr<ResourceObject>& resObj) {
        auto pattern = weak.Upgrade();
        CHECK_NULL_VOID(pattern);
        std::string src =
            ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetMediaPath(resObj->GetId());
        auto params = resObj->GetParams();
        if (src.empty() && params.size() && params[0].value.has_value()) {
            if (resObj->GetType() == static_cast<int32_t>(ResourceType::RAWFILE)) {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetRawfile(
                    params[0].value.value());
            } else {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetMediaPathByName(
                    params[0].value.value());
            }
        }
        if (resObj->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
            if (resObj->GetId() == -1 && params.size() && params[0].value.has_value()) {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetStringByName(
                    params[0].value.value());
            } else if (resObj->GetId() != -1) {
                src = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resObj)->GetString(
                    resObj->GetId());
            }
        }
        RefPtr<PixelMap> pixmap = nullptr;
        auto srcInfo = CreateSourceInfo(src, pixmap, resObj->GetBundleName(), resObj->GetModuleName());
        pattern->UpdateImageAlt(srcInfo);
        pattern->OnConfigurationUpdate();
    };
    pattern->AddResObj(key, resObj, std::move(updateFunc));
}

void HandleFillColorResource(const RefPtr<ResourceObject>& resObj, const RefPtr<ImagePattern>& pattern)
{
    std::string key = "image.fillcolor";
    pattern->RemoveResObj(key);
    CHECK_NULL_VOID(resObj);
    auto updateFunc = [weak = AceType::WeakClaim(AceType::RawPtr(pattern))](const RefPtr<ResourceObject>& resObj) {
        auto pattern = weak.Upgrade();
        CHECK_NULL_VOID(pattern);
        Color color;
        bool status = ResourceParseUtils::ParseResColor(resObj, color);
        if (!status) {
            if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
                return;
            }
            auto pipelineContext = PipelineBase::GetCurrentContext();
            CHECK_NULL_VOID(pipelineContext);
            auto theme = pipelineContext->GetTheme<ImageTheme>();
            CHECK_NULL_VOID(theme);
            color = theme->GetFillColor();
        }
        pattern->UpdateImageFill(color);
    };
    pattern->AddResObj(key, resObj, std::move(updateFunc));
}

void HandleBorderRadiusResource(const RefPtr<ResourceObject>& resObj, const RefPtr<ImagePattern>& pattern)
{
    std::string key = "image.borderRadius";
    std::string borderRadiusKey = "image.borderRadius.edges";
    std::string radiusKey = "borderRadius";
    pattern->RemoveResObj(key);
    pattern->RemoveResObj(borderRadiusKey);
    pattern->RemoveResObj(radiusKey);
    CHECK_NULL_VOID(resObj);
    auto updateFunc = [weak = AceType::WeakClaim(AceType::RawPtr(pattern))](const RefPtr<ResourceObject>& resObj) {
        auto pattern = weak.Upgrade();
        CHECK_NULL_VOID(pattern);
        auto frameNode = pattern->GetHost();
        CHECK_NULL_VOID(frameNode);
        CalcDimension borderRadiusValue;
        bool status = ResourceParseUtils::ParseResDimensionVp(resObj, borderRadiusValue);
        if (status) {
            BorderRadiusProperty borderRadius;
            borderRadius.SetRadius(borderRadiusValue);
            borderRadius.multiValued = false;
            ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, NeedBorderRadius, true, frameNode);
            ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, BorderRadius, borderRadius, frameNode);
            pattern->SetNeedBorderRadius(true);
        }
    };
    pattern->AddResObj(key, resObj, std::move(updateFunc));
}

void ImageModelNG::CreateWithResourceObj(ImageResourceType resourceType, const RefPtr<ResourceObject>& resObj)
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    CHECK_NULL_VOID(frameNode);
    CreateWithResourceObj(frameNode, resourceType, resObj);
}

void ImageModelNG::CreateWithResourceObj(
    FrameNode* frameNode, ImageResourceType resourceType, const RefPtr<ResourceObject>& resObj)
{
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    switch (resourceType) {
        case ImageResourceType::SRC:
            HandleSrcResource(resObj, pattern);
            break;
        case ImageResourceType::FILL_COLOR:
            HandleFillColorResource(resObj, pattern);
            break;
        case ImageResourceType::ALT:
            HandleAltResource(resObj, pattern);
            break;
        case ImageResourceType::BORDER_RADIUS:
            HandleBorderRadiusResource(resObj, pattern);
            break;
        default:
            break;
    }
}

void ImageModelNG::SetImageFillSetByUser(bool value)
{
    if (SystemProperties::ConfigChangePerform()) {
        ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, ImageFillSetByUser, value);
    }
}

void ImageModelNG::SetSupportSvg2(bool enable)
{
    auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
    SetSupportSvg2(frameNode, enable);
}

void ImageModelNG::SetSupportSvg2(FrameNode* frameNode, bool enable)
{
    CHECK_NULL_VOID(frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->SetSupportSvg2(enable);
}

void ImageModelNG::ResetSupportSvg2(FrameNode* frameNode)
{
    SetSupportSvg2(frameNode, false);
}

bool ImageModelNG::GetSupportSvg2(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    auto imagePattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_RETURN(imagePattern, false);
    return imagePattern->GetSupportSvg2();
}

void ImageModelNG::SetContentTransition(ContentTransitionType contentTransition)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, ContentTransition, contentTransition);
}

void ImageModelNG::SetContentTransition(FrameNode* frameNode, ContentTransitionType contentTransition)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, ContentTransition, contentTransition, frameNode);
}

ContentTransitionType ImageModelNG::GetContentTransition(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, ContentTransitionType::IDENTITY);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, ContentTransitionType::IDENTITY);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), ContentTransitionType::IDENTITY);
    return paintProperty->GetImagePaintStyle()->GetContentTransition().value_or(ContentTransitionType::IDENTITY);
}

void ImageModelNG::SetAltError(const ImageSourceInfo& src)
{
    if (ImageSourceInfo::ResolveURIType(src.GetSrc()) == SrcType::NETWORK) {
        ImageSourceInfo defaultSrcInfo("");
        ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, defaultSrcInfo);
    }
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, src);
}

void ImageModelNG::SetAltError(FrameNode* frameNode, const ImageSourceInfo& src)
{
    if (ImageSourceInfo::ResolveURIType(src.GetSrc()) == SrcType::NETWORK) {
        ImageSourceInfo defaultSrcInfo("");
        ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, defaultSrcInfo, frameNode);
    }
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, src, frameNode);
}

void ImageModelNG::SetAltErrorResource(FrameNode* frameNode, void* resource)
{
    CHECK_NULL_VOID(frameNode);
    auto res = reinterpret_cast<ArkUI_Resource*>(resource);
    CHECK_NULL_VOID(res);
    RefPtr<PixelMap> pixMapPtr = nullptr;
    auto srcInfo = CreateSourceInfo(res->src, pixMapPtr, res->bundleName, res->moduleName);
    srcInfo.SetIsUriPureNumber(res->resId == -1);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, srcInfo, frameNode);
}

void ImageModelNG::SetAltErrorPixelMap(FrameNode* frameNode, void* pixelMap)
{
    CHECK_NULL_VOID(frameNode);
    CHECK_NULL_VOID(pixelMap);
#ifndef ACE_UNITTEST
    RefPtr<PixelMap> pixelMapPtr = PixelMap::GetFromDrawable(pixelMap);
    auto srcInfo = CreateSourceInfo("", pixelMapPtr, "", "");
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, srcInfo, frameNode);
#endif
}

ImageSourceInfo ImageModelNG::GetAltError(FrameNode* frameNode)
{
    ImageSourceInfo defaultImageSourceInfo;
    CHECK_NULL_RETURN(frameNode, defaultImageSourceInfo);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, defaultImageSourceInfo);
    return layoutProperty->GetAltError().value_or(defaultImageSourceInfo);
}

void ImageModelNG::SetAltPlaceholder(const ImageSourceInfo& src)
{
    ACE_UPDATE_LAYOUT_PROPERTY(ImageLayoutProperty, AltPlaceholder, src);
}

void ImageModelNG::SetAltPlaceholder(FrameNode* frameNode, const ImageSourceInfo& src)
{
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltPlaceholder, src, frameNode);
}

void ImageModelNG::SetAltPlaceholderResource(FrameNode* frameNode, void* resource)
{
    CHECK_NULL_VOID(frameNode);
    auto res = reinterpret_cast<ArkUI_Resource*>(resource);
    CHECK_NULL_VOID(res);
    RefPtr<PixelMap> pixMapPtr = nullptr;
    auto srcInfo = CreateSourceInfo(res->src, pixMapPtr, res->bundleName, res->moduleName);
    srcInfo.SetIsUriPureNumber(res->resId == -1);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltPlaceholder, srcInfo, frameNode);
}

void ImageModelNG::SetAltPlaceholderPixelMap(FrameNode* frameNode, void* pixelMap)
{
    CHECK_NULL_VOID(frameNode);
    CHECK_NULL_VOID(pixelMap);
#ifndef ACE_UNITTEST
    RefPtr<PixelMap> pixelMapPtr = PixelMap::GetFromDrawable(pixelMap);
    auto srcInfo = CreateSourceInfo("", pixelMapPtr, "", "");
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltPlaceholder, srcInfo, frameNode);
#endif
}

ImageSourceInfo ImageModelNG::GetAltPlaceholder(FrameNode* frameNode)
{
    ImageSourceInfo defaultImageSourceInfo;
    CHECK_NULL_RETURN(frameNode, defaultImageSourceInfo);
    auto layoutProperty = frameNode->GetLayoutProperty<ImageLayoutProperty>();
    CHECK_NULL_RETURN(layoutProperty, defaultImageSourceInfo);
    return layoutProperty->GetAltPlaceholder().value_or(defaultImageSourceInfo);
}

void ImageModelNG::ResetImageAltError(FrameNode* frameNode)
{
    CHECK_NULL_VOID(frameNode);
    ImageSourceInfo sourceInfo("");
    sourceInfo.SetIsFromReset(true);
    ACE_UPDATE_NODE_LAYOUT_PROPERTY(ImageLayoutProperty, AltError, sourceInfo, frameNode);
    auto pattern = frameNode->GetPattern<ImagePattern>();
    CHECK_NULL_VOID(pattern);
    pattern->ResetAltImageError();
}

void ImageModelNG::SetAntiAlias(bool antiAlias)
{
    ACE_UPDATE_PAINT_PROPERTY(ImageRenderProperty, AntiAlias, antiAlias);
}

void ImageModelNG::SetAntiAlias(FrameNode* frameNode, bool antiAlias)
{
    ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, AntiAlias, antiAlias, frameNode);
}

bool ImageModelNG::GetAntiAlias(FrameNode* frameNode)
{
    CHECK_NULL_RETURN(frameNode, false);
    auto paintProperty = frameNode->GetPaintProperty<ImageRenderProperty>();
    CHECK_NULL_RETURN(paintProperty, false);
    CHECK_NULL_RETURN(paintProperty->GetImagePaintStyle(), false);
    return paintProperty->GetImagePaintStyle()->GetAntiAlias().value_or(false);
}
} // namespace OHOS::Ace::NG
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_IMAGE_IMAGE_MODEL_NG_CPP
